package com.flow.asyncflow.core.node;


import com.flow.asyncflow.core.annotation.NodeInfo;
import com.flow.asyncflow.core.entity.config.AsyncFlowInfo;
import com.flow.asyncflow.core.entity.core.AsyncFlowContext;
import com.flow.asyncflow.core.entity.core.AsyncFlowNodeResponse;
import com.flow.asyncflow.core.entity.core.AsyncFlowRequest;
import com.flow.asyncflow.core.entity.core.AsyncFlowResponse;
import com.flow.asyncflow.core.enums.ExecuteEnum;
import com.flow.asyncflow.core.utils.log.asyncflowlog.AsyncFlowCommon_Log;
import com.flow.asyncflow.core.utils.msg.AsyncFlowSendMsg;
import org.springframework.util.StopWatch;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

@NodeInfo(name = "请求参数（AsyncFlowRequest）验证&构建上下文")
public class AsyncFlowBaseValidator {

    //region 请求参数验证&构建上下文

    /**
     * 请求参数验证&构建上下文
     *
     * @param asyncFlowContext 上下文
     * @param request          请求
     * @param clazzRes         返回
     * @param reqTypeEnum      节点操作类型Enum
     * @param clazzContext     上下文Class
     * @param <TReq>           请求参数类型泛型
     * @param <TRes>           返回参数类型泛型
     * @param <TExeEnum>       节点操作类型泛型
     */
    public <TReq, TRes extends AsyncFlowResponse, TExeEnum> void buildAsyncFlowRequestAndContext(AsyncFlowRequest asyncFlowRequest, AsyncFlowContext asyncFlowContext, TReq request, Class<TRes> clazzRes, TExeEnum reqTypeEnum, Class<?> clazzContext, AsyncFlowInfo asyncFlowInfo, LinkedHashMap<ExecuteEnum, Long> timeConsuming) {

        StopWatch sw = new StopWatch();
        sw.start("异步流基础验证" + "-开始");
        Date startTime = new Date();
        AsyncFlowNodeResponse nodeResponse = new AsyncFlowNodeResponse(200, "成功");
        Object context = null;
        TRes response = null;

        //节点操作类型枚举Msg
        String operatorEnumMsg = "";
        try {
            response = clazzRes.newInstance();
            context = clazzContext.newInstance();


            //此处的getMsg  需要跟操作类型枚举里面的msg 的属性名称保持一致，
            Method getMessage = reqTypeEnum.getClass().getMethod("getMsg");
            operatorEnumMsg = (String) getMessage.invoke(reqTypeEnum);
        } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
            e.printStackTrace();
            String s = AsyncFlowSendMsg.buildErrorMsg(asyncFlowRequest, e, "构建请求参数和上下文", asyncFlowInfo);
            AsyncFlowSendMsg.sendQYWXMsg(asyncFlowInfo.getFlowMaintainName(), s, asyncFlowInfo.getNodeArmUrl());
        }
        asyncFlowRequest.setReqTypeEnumName(reqTypeEnum.toString());
        asyncFlowRequest.setReqTypeEnumMsg(operatorEnumMsg);
        asyncFlowRequest.setRequestObj(request);

        //这个放在首位，后面的set需要用到这个
        asyncFlowContext.setAsyncFlowInfo(asyncFlowInfo);
        asyncFlowContext.setAsyncFlowRequest(asyncFlowRequest);
        asyncFlowContext.setRequest(request);
        asyncFlowContext.setResponse(response);
        asyncFlowContext.setReqTypeEnum(reqTypeEnum);
        asyncFlowContext.setContext(context);
        AsyncFlowCommon_Log.AddAsyncFlowLog(asyncFlowRequest, nodeResponse, asyncFlowContext, new AsyncFlowBaseValidator(), startTime, ExecuteEnum.Validator, false);
        sw.stop();
        timeConsuming.put(ExecuteEnum.Validator, sw.getTotalTimeMillis());
    }


    //endregion
}
